﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SuuntoAmbitConnector;
using System.Text;

namespace SuuntoAmbitConnectorTests
{
    [TestClass]
    public class WorkoutTests
    {        
        [TestMethod]
        public void TestWorkoutCreationWithMinimumInputData()
        {
            var expectedStartDate = DateTime.Now;
            var expectedActivity = 1;
            var expectedDurationSec = 180 * 60 + 21 * 60 + 45;
            var expectedComment = "testcomment";

            var workout = new Workout(expectedStartDate, expectedActivity, expectedDurationSec, expectedComment);

            Assert.AreEqual(expectedStartDate, workout.StartDate, "Unexpected workout Date");
            Assert.AreEqual(expectedActivity, workout.Activity, "Unexpected workout activity");
            Assert.AreEqual(expectedDurationSec, workout.DurationInSeconds, "Unexpected workout duration");
            Assert.AreEqual(expectedComment, workout.Comment, "Unexpected workout comment");
        }

        [TestMethod]
        public void TestWorkoutCreationWithHourMinuteSecondConstructor()
        {
            var expectedStartDate = DateTime.Now;
            var expectedActivity = 1;
            var hourPart = 2;
            var minutePart = 21;
            var secondPart = 35;
            var expectedDurationInSeconds = hourPart * 60 * 60 + minutePart * 60 + secondPart;
            var expectedComment = "testcomment";

            var workout = new Workout(expectedStartDate, expectedActivity, hourPart, minutePart, secondPart, expectedComment);

            Assert.AreEqual(expectedStartDate, workout.StartDate, "Unexpected workout Date");
            Assert.AreEqual(expectedActivity, workout.Activity, "Unexpected workout activity");
            Assert.AreEqual(expectedDurationInSeconds, workout.DurationInSeconds, "Unexpected workout duration");
            Assert.AreEqual(expectedComment, workout.Comment, "Unexpected workout comment");
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestWorkoutCreationWithInvalidDurationThrowsArgumentException()
        {
            var unexpectedDuration = -1;
            
            var workout = new Workout(DateTime.Now, 1, unexpectedDuration, string.Empty);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestWorkoutCreationWithInvalidDurationHourThrowsArgumentException()
        {
            var unexpectedDurationHourPart = -1;

            var workout = new Workout(DateTime.Now, 1, unexpectedDurationHourPart, 0, 0, string.Empty);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestWorkoutCreationWithInvalidDurationMinuteThrowsArgumentException()
        {
            var unexpectedDurationMinutePart = -1;

            var workout = new Workout(DateTime.Now, 1, 0, unexpectedDurationMinutePart, 0, string.Empty);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestWorkoutCreationWithInvalidDurationSecondThrowsArgumentException()
        {
            var unexpectedDurationSecondPart = -1;

            var workout = new Workout(DateTime.Now, 1, 0, 0, unexpectedDurationSecondPart, string.Empty);
        }

        [TestMethod]
        public void TestWorkoutModification()
        {
            var expectedDistanceInMeter = 60 * 1000 + 3 * 100;
            var workout = new Workout(DateTime.Now, 1, 90, string.Empty);

            workout.DistanceInMeters = expectedDistanceInMeter;

            Assert.AreEqual(expectedDistanceInMeter, workout.DistanceInMeters, "Unexpected workout distance");     
        }

        [TestMethod]
        public void TestRetrievingDurationHourPart()
        {
            var expectedHourPart = 2;
            var workout = new Workout(DateTime.Now, 1, expectedHourPart * 60 * 60 + 35, string.Empty);

            Assert.AreEqual(expectedHourPart, workout.GetDurationHourPart(), "Unexpected workout duration hour part");            
        }

        [TestMethod]
        public void TestRetrievingDurationMinutePart()
        {
            var expectedMinutePart = 21;
            var workout = new Workout(DateTime.Now, 1, expectedMinutePart * 60 + 35, string.Empty);

            Assert.AreEqual(expectedMinutePart, workout.GetDurationMinutePart(), "Unexpected workout duration minute part");
            
        }

        [TestMethod]
        public void TestRetrievingDurationSecondPart()
        {
            var expectedSecondPart = 35;
            var workout = new Workout(DateTime.Now, 1, 1 * 60 * 60 + expectedSecondPart, string.Empty);

            Assert.AreEqual(expectedSecondPart, workout.GetDurationSecondPart(), "Unexpected workout duration second part");
        }

        [TestMethod]
        public void TestRetrievingDistanceKilometerPart()
        {
            var expectedKilometerPart = 3;
            var workout = new Workout(DateTime.Now, 3, 60000, string.Empty);
            workout.DistanceInMeters = 3546;

            Assert.AreEqual(expectedKilometerPart, workout.GetDistanceKilometerPart(), "Unexpected workout distance kilometer part");
        }

        [TestMethod]
        public void TestRetrievingDistanceMeterPart()
        {
            var expectedKilometerPart = 546;
            var workout = new Workout(DateTime.Now, 3, 60000, string.Empty);
            workout.DistanceInMeters = 3546;

            Assert.AreEqual(expectedKilometerPart, workout.GetDistanceMeterPart(), "Unexpected workout distance meter part");
        }

        [TestMethod]
        public void TestToStringWithMinimumRequiredData()
        {
            var workout = new Workout(DateTime.Now, 3, 3000, "testcomment");

            StringBuilder expectedOutput = new StringBuilder();
            expectedOutput.AppendLine(string.Format("Start date: {0}", workout.StartDate.ToString("yyyy-MM-dd")));
            expectedOutput.AppendLine(string.Format("Activity: {0}", workout.Activity));
            expectedOutput.AppendLine(string.Format("Duration: {0}h {1}min {2}sec", workout.GetDurationHourPart(), workout.GetDurationMinutePart(), workout.GetDurationSecondPart()));            
            expectedOutput.AppendLine(string.Format("Comment: {0}", workout.Comment));

            Assert.AreEqual(expectedOutput.ToString(), workout.ToString(), "Unexpected string representation of the workout");
        }

        [TestMethod]
        public void TestToStringWithExtendedData()
        {
            var workout = new Workout(DateTime.Now, 3, 3000, "testcomment");
            workout.DistanceInMeters = 3456;

            StringBuilder expectedOutput = new StringBuilder();
            expectedOutput.AppendLine(string.Format("Start date: {0}", workout.StartDate.ToString("yyyy-MM-dd")));
            expectedOutput.AppendLine(string.Format("Activity: {0}", workout.Activity));
            expectedOutput.AppendLine(string.Format("Duration: {0}h {1}min {2}sec", workout.GetDurationHourPart(), workout.GetDurationMinutePart(), workout.GetDurationSecondPart()));
            expectedOutput.AppendLine(string.Format("Distance: {0}km {1}m", workout.GetDistanceKilometerPart(), workout.GetDistanceMeterPart()));
            expectedOutput.AppendLine(string.Format("Comment: {0}", workout.Comment));

            Assert.AreEqual(expectedOutput.ToString(), workout.ToString(), "Unexpected string representation of the workout");
        }
    }
}
